package com.neusoft.elmboot.filter;

import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.neusoft.elmboot.common.AutheAuthoResp;
import com.neusoft.elmboot.common.Constants;
import com.neusoft.elmboot.common.Result;
import com.neusoft.elmboot.exception.UnLoginException;
import com.neusoft.elmboot.po.Permission;
import com.neusoft.elmboot.po.Role;
import com.neusoft.elmboot.po.User;
import com.neusoft.elmboot.utils.JWTUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.filter.GenericFilterBean;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

@Slf4j
public class JwtFilter extends GenericFilterBean {

    private static final String AUTH_HEADER = "elm-token";
    private static final String TOKEN_PREFIX = "";



   @Override 
   public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
           throws IOException, ServletException {

	   HttpServletRequest req = (HttpServletRequest) servletRequest;
       String requestUrl = req.getRequestURI();
       log.info("-------1.JwtFilter.doFilter() -> requestUrl : "+requestUrl+" , referer : "+req.getHeader("Referer"));
       if(Constants.IGNORE_AUTHORIZE_URLS.length > 0) {
           for (String ignoreAuthorizeUrl : Constants.IGNORE_AUTHORIZE_URLS) {
               if (requestUrl.indexOf(ignoreAuthorizeUrl)>-1) {
                   filterChain.doFilter(req, servletResponse);
                   logger.info("-----ignore authorize url:"+requestUrl);
                   return;
               }
           }
       }
       // 从请求头中获取Token
       String token = req.getHeader(AUTH_HEADER);

       // 校验Token
       if (token == null || !token.startsWith(TOKEN_PREFIX)) {
//            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
           try {
               log.error("-------2.JwtFilter,token is null!");
               throw new UnLoginException("您未登录！");
           } catch (UnLoginException e) {
               AutheAuthoResp.tokenNullResponse(req,(HttpServletResponse) servletResponse);
               return;
           }
       }

       try {
           // 去掉Token前缀
           token = token.replace(TOKEN_PREFIX, "");

           // 解析Token并验证
           String username = JWTUtil.getUsernameFromToken(token);
           if (!JWTUtil.validateToken(token)) {
//                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
               throw new UnLoginException("Token不合法！");
//                return false; // 拦截请求
           }

           // 在请求中添加用户名信息
//            request.setAttribute("username", username);

           Claim claim = JWTUtil.getClaim(token, "authorities");//获取权限
           List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList(claim.asString());
           UsernamePasswordAuthenticationToken upaToken = new UsernamePasswordAuthenticationToken(username, null, authorities);
           SecurityContextHolder.getContext().setAuthentication(upaToken);

           // 验证是否有访问权限

           // 根据用户的角色信息，判断用户是否有权限访问该URL
           boolean hasPermission = checkPermission(authorities, requestUrl);
           logger.info("------hasPermission:" + hasPermission);
           // 如果用户有权限访问该URL，则允许请求继续执行
           if (hasPermission) {
               filterChain.doFilter(servletRequest, servletResponse);
           } else {
               // 如果用户没有权限访问该URL，则返回无权限提示
               HttpServletResponse response = (HttpServletResponse)servletResponse;
               logger.info("------当前用户无权访问！");
//               response.sendError(HttpServletResponse.SC_FORBIDDEN);
               AutheAuthoResp.accessDeniedResponse(req,response);
           }

       } catch (Exception e) {
//            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
           if (e instanceof JWTVerificationException) {
               try {
                   log.error("-------3.JwtFilter,Token校验失败！!");
                   throw new UnLoginException("Token校验失败！");
               } catch (UnLoginException ex) {
                   log.error("-------4.JwtFilter,UnLoginException...");
                   throw new RuntimeException(ex);
               }
           } else if (e instanceof UnLoginException) {
               log.error("-------5.JwtFilter,UnLoginException...");
                   throw new RuntimeException(e);
           }
           try {
               log.error("-------6.JwtFilter,e...");
               throw e;
           } catch (UnLoginException ex) {
               throw new RuntimeException(ex);
           }
       }

   }

    private User getCurrentUser() {
        // 获取当前登录用户的逻辑，例如从Spring Security上下文中获取
        // 注意：这部分逻辑需要根据具体的认证框架来实现
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null && authentication.getPrincipal() instanceof User) {
            return (User) authentication.getPrincipal();
        }
        return null;
    }

    private boolean checkPermission(List<GrantedAuthority> authorities, String requestUrl) {
        if (authorities != null) {
            // 根据用户的权限信息，判断是否有权限访问该URL
            for (GrantedAuthority permission : authorities) {
                if("*".equals(permission.getAuthority())) {
                    return true;
                }
                if (permissionMatchesUrl(permission.getAuthority(), requestUrl)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     *
     * @param permission - 数据库中的权限URL  ： GET /food/list
     * @param requestUrl - 当前浏览器请求的URL : /elm/food/list
     * @return
     */
    private boolean permissionMatchesUrl(String permission, String requestUrl) {
        logger.info("-------permissionMatchesUrl()->--db authorityUrl=["+permission+"] requestUrl="+requestUrl);
        if (permission == null) {
            return false;
        }
        /*if ("*".equals(permission)) {
            return  true;
        }*/
//        String s = permission.split(" ")[1];
        String[] perArray = permission.split(" ");
        if (null !=  perArray && perArray.length > 1) {
            return requestUrl.indexOf(perArray[1]) > -1 ;
        }
        return false ;
    }
} 